<?php

namespace Dongasai\WkProtoPhp\Packets;

use Dongasai\WkProtoPhp\Enums\FrameType;
use Dongasai\WkProtoPhp\Framer;
use Dongasai\WkProtoPhp\Encoder;
use Dongasai\WkProtoPhp\Decoder;
use Dongasai\WkProtoPhp\Enums\ReasonCode;

/**
 * DISCONNECT断开连接包
 */
class DisconnectPacket extends Framer
{
    private int $reasonCode = ReasonCode::SUCCESS->value;
    private string $reason = '';

    public function __construct()
    {
        parent::__construct(FrameType::DISCONNECT->value);
    }

    public function getFrameType(): int
    {
        return FrameType::DISCONNECT->value;
    }

    public function __toString(): string
    {
        return sprintf(
            'DISCONNECT ReasonCode:%s Reason:%s',
            ReasonCode::toString($this->reasonCode),
            $this->reason
        );
    }

    // Getters and Setters
    public function getReasonCode(): int
    {
        return $this->reasonCode;
    }

    public function setReasonCode(int $reasonCode): void
    {
        $this->reasonCode = $reasonCode;
    }

    public function getReason(): string
    {
        return $this->reason;
    }

    public function setReason(string $reason): void
    {
        $this->reason = $reason;
    }

    /**
     * 解码DISCONNECT包
     */
    public static function decode(Framer $framer, string $data, int $version): self
    {
        $decoder = new Decoder($data);
        $packet = new self();
        
        // 复制framer属性
        $packet->setRemainingLength($framer->getRemainingLength());
        $packet->setNoPersist($framer->getNoPersist());
        $packet->setRedDot($framer->getRedDot());
        $packet->setSyncOnce($framer->getSyncOnce());
        $packet->setDUP($framer->getDUP());
        $packet->setFrameSize($framer->getFrameSize());

        try {
            $packet->reasonCode = $decoder->uint8();
            $packet->reason = $decoder->string();
        } catch (\Exception $e) {
            throw new \RuntimeException('解码DISCONNECT包失败: ' . $e->getMessage(), 0, $e);
        }

        return $packet;
    }

    /**
     * 编码DISCONNECT包
     */
    public function encode(Encoder $encoder, int $version): void
    {
        $encoder->writeUint8($this->reasonCode & 0xFF);
        $encoder->writeString($this->reason);
    }

    /**
     * 计算DISCONNECT包大小
     */
    public function size(int $version): int
    {
        $size = 0;
        $size += 1; // ReasonCodeByteSize
        $size += 2 + strlen($this->reason); // StringFixLenByteSize + reason length
        return $size;
    }
}